<?php
 
 error_reporting(E_ALL);
 ini_set("display_errors", 1);
 
 include_once "../common/base.php";
 require_once('lib/ImapMailbox.php');
 require_once('lib/google-api-php-client-master/autoload.php');
 
class fetcher
{
    private $_db;
	private $campaigns = array();
	private $imap_info = array();
	private $smtp_info = array();
	private $filter = array();
    private $msg_cnt = array();
    private $delay_msg_cnt = array();
	private $client;
	private $log_level;
	
    public function __construct($db=NULL)
    {
        if(is_object($db))
        {
            $this->_db = $db;
        }
        else
        {
            $dsn = "mysql:host=".DB_HOST.";dbname=".DB_NAME;
            $this->_db = new PDO($dsn, DB_USER, DB_PASS);
        }
        $this->client = new Google_Client();
    }
	
	public function init(){
        $this->log_level = 2;
		$this->listCampaigns();
		$this->listImap();
		$this->listSmtp();
		$this->listFilter();
		$this->countCampaignMessage();
        $this->countCampaignDelayMessage();
		$this->gmail_client();
		
	}
	
	public function getClientInfo(){
        $client_info = array ();
        $sql = "SELECT *
                FROM client_info";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            if($stmt->rowCount()!=0) 
            {
                $row = $stmt->fetch();
                $client_info['client_id'] = $row['client_id'];
                $client_info['client_secret'] = $row['client_secret'];
                $client_info['alias_redirect'] = $row['alias_redirect'];
            }
        }
        return $client_info;
    }
	
	public function gmail_client(){
        $client_info = $this->getClientInfo();
        $client_id = $client_info['client_id']; //'1097530924560-9dv7lmvrmlfsdrn3rbd8a197ci34n4og.apps.googleusercontent.com';
        $client_secret = $client_info['client_secret']; //'VMTuLVpXMyjbdi_EoyeJxUnr';
        $redirect_uri = $client_info['alias_redirect']; //'http://www.bytefact.com/mesbagapi.php';

        $this->client->setClientId($client_id);
        $this->client->setClientSecret($client_secret);
	}
	
	public function getRefreshTokenFromDB($mail_id){
        $sql = "SELECT refresh_token
                FROM alias_mail WHERE mail_id=:mail_id";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->bindParam(":mail_id", $mail_id, PDO::PARAM_STR);
            $stmt->execute();
            $row = $stmt->fetch();
            if(!isset($row['refresh_token'])){
                $sql = "SELECT refresh_token
                FROM sub_master_mail WHERE mail_id=:mail_id";
                if($stmt = $this->_db->prepare($sql)) {
                    $stmt->bindParam(":mail_id", $mail_id, PDO::PARAM_STR);
                    $stmt->execute();
                    $row = $stmt->fetch();
                    return $row['refresh_token'];
                }
            }
            else return $row['refresh_token'];
        }
	}
	
	public function refreshToken(&$old_access_token, $mail_id){
        try {
            $this->client->setAccessToken($old_access_token);
            if($this->client->isAccessTokenExpired()){
                if($this->log_level > 1) echo "User token expired.". "<br/>";
                if($this->log_level > 1) echo "Old Access token:" . $old_access_token . "<br/>";
                $google_token = $this->getRefreshTokenFromDB($mail_id);
                $this->client->refreshToken($google_token);
                $access_token = $this->client->getAccessToken();
                if($this->log_level > 1) echo "New Access token:" . $access_token . "<br/>";
                
                $sql = "UPDATE alias_mail SET password=:access_token WHERE mail_id=:mail_id";
                if($stmt = $this->_db->prepare($sql)) {
                    $stmt->bindParam(":mail_id", $mail_id, PDO::PARAM_STR);
                    $stmt->bindParam(":access_token", $access_token, PDO::PARAM_STR);
                    $stmt->execute();
                }
                $sql = "UPDATE sub_master_mail SET password=:access_token WHERE mail_id=:mail_id";
                if($stmt = $this->_db->prepare($sql)) {
                    $stmt->bindParam(":mail_id", $mail_id, PDO::PARAM_STR);
                    $stmt->bindParam(":access_token", $access_token, PDO::PARAM_STR);
                    $stmt->execute();
                }
                $old_access_token = $access_token;
            }
        }
        catch(Exception $ex){
            echo $ex->getMessage();
        }
    }
	
	public function readNewGmail($user_id, &$password){
        $messages = array();
        //refresh token if necessary
        $this->refreshToken($password, $user_id);
        
        $this->client->setAccessToken($password);
        $service = new Google_Service_Gmail($this->client);
        $optParams = array();
        //$optParams['q'] = 'is:unread category:primary';
        $optParams['q'] = 'is:unread';
        try{
            $gpaimessages = $service->users_messages->listUsersMessages($user_id,$optParams);
        }
        catch(Exception $ex){
            echo $ex->getMessage();
        }
        if(!isset($gpaimessages) || !isset($gpaimessages['modelData'])){
            if($this->log_level > 1) echo "Gmail connection failed:" . "<br/>";
            return false;
        }
        if(isset($gpaimessages['modelData']) && isset($gpaimessages['modelData']['messages']))
            $messages = $gpaimessages['modelData']['messages'];
        if($this->log_level > 3){
            echo "New mails:" . "<br/>";
            var_dump($messages);
            echo "<br/>";
        }
        return $messages;
	}
	
	public function getGmailsInfo($messages, $user_id, &$password ){
        
        //refresh token if necessary
        $this->refreshToken($password, $user_id);
        
        $this->client->setAccessToken($password);
        //init servic
        $service = new Google_Service_Gmail($this->client);
        
        //init lebel to unread
        $postbody = new Google_Service_Gmail_ModifyThreadRequest;
        $postbody->setRemoveLabelIds(array('UNREAD'));

        $optParams = array();
        $optParams['format'] = 'metadata';
        $optParams['metadataHeaders'] = array('To','From','Message-ID','Subject');
        
        $headers = array();
        foreach($messages as $mail){
            $header = $service->users_messages->get($user_id, $mail['id'], $optParams);
            $obj = (object) array('to'=> '', 'from'=>'', 'subject'=>'', 'message_id'=> '');
            $mj = $header['modelData']['payload']['headers'];
            foreach ($mj as $m){
                    if($m['name'] == 'To') $obj->to = $m['value'];
                    if($m['name'] == 'From') $obj->from = $m['value'];
                    if($m['name'] == 'Subject') $obj->subject = $m['value'];
                    if($m['name'] == 'Message-ID') $obj->message_id = $m['value'];
            }
            array_push($headers, $obj);

            //mark mails as read
            $service->users_threads->modify($user_id, $mail['threadId'],$postbody);
        }
        return $headers;
	}
	
	public function listFilter(){
	    $sql = "SELECT mail_id
                FROM filter where mail_id != 'ANY'";
		if($stmt = $this->_db->prepare($sql)) {
		    $stmt->execute();
		    if($stmt->rowCount()==0) 
		    {
			//echo "Empty campaign table.";
		    }
		    else{
			for($i=0 ; $i<$stmt->rowCount() ; $i++){
			    $row = $stmt->fetch();
			    //$this->filter[$row['mail_id']] = 1;
			    array_push($this->filter, $row['mail_id']);
			}
		    }
		}
		else{
			echo "Error! Sorry, Error in SQL.";
		}
	}
   
   public function getSubmasterInfo($mail_id){
	    $sql = "SELECT *
                FROM sub_master_mail WHERE mail_id=:mail_id";
        if($stmt = $this->_db->prepare($sql)) {
			$stmt->bindParam(":mail_id", $mail_id, PDO::PARAM_STR);
            $stmt->execute();
    		$row = $stmt->fetch();
			return $row;
		}
		else
		{
        	echo "No sub_master_mail info found, this should not happen";
        }
   }
   
   public function getAliasInfo($mail_id){
	    $sql = "SELECT *
                FROM alias_mail WHERE mail_id=:mail_id";
        if($stmt = $this->_db->prepare($sql)) {
			$stmt->bindParam(":mail_id", $mail_id, PDO::PARAM_STR);
            $stmt->execute();
    		$row = $stmt->fetch();
			return $row;
		}
		else
		{
        	echo "No alias_mail info found, this should not happen";
        }
   }
   
   public function listCampaigns(){
		//	campaigns structure:
		//	$campaigns
		// 		array
		//			[campaign_id]
		//			arrary
		//				[user]
		//					[user_id]
		//					[user_info]
		
		$user_map = array();
		
		$sql = "SELECT *
                FROM campaign where is_activated = 1";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            if($stmt->rowCount()==0) 
			{
                echo "Empty campaign table.";
            }
			else
			{
				for($i=0 ; $i<$stmt->rowCount() ; $i++){
    				$row = $stmt->fetch();
					$campaign = array('campaign_id', 'users');
					$campaign['campaign_id'] = $row['campaign_id'];
					$campaign['users'] = array();
					$user  = array('user_id', 'user_info');
					$user['user_id'] = $row['sub_master_mail_id'];
					$user['user_info'] = $this->getSubmasterInfo($row['sub_master_mail_id']);
					array_push($campaign['users'], $user); 
					array_push($this->campaigns, $campaign);
					//$user_map[$user['user_id']] = 1;
				}
			}
		}
		else
		{
        	echo "Error! Sorry, Error in SQL.";
        }	
		$count = 0;
		foreach($this->campaigns as $campaign){
				$campaign_id = $campaign['campaign_id'];
				$sql = "SELECT mail_id
                FROM alias_mail where campaign_id =:campaign_id";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":campaign_id", $campaign_id, PDO::PARAM_INT);
					$stmt->execute();
					if($stmt->rowCount()==0) 
					{
						echo "Empty message table.";
					}
					else
					{
						for($i=0 ; $i<$stmt->rowCount() ; $i++){
							$row = $stmt->fetch();
							
							//if this user is already added for checking, skip it.
							if(isset($user_map[$row['mail_id']])) continue;
							$user_map[$row['mail_id']] = 1;
							
							$user  = array('user_id', 'user_info');
							$user['user_id'] = $row['mail_id'];
							$user['user_info'] = $this->getAliasInfo($row['mail_id']);
							array_push($this->campaigns[$count]['users'], $user);
						}
					}
				}
				else
				{
					echo "Error! Sorry, Error in SQL.";
				}
				$count++;
		}
		/*
		//Print campaing wise unique users
		foreach($this->campaigns as $campaign){
			echo "campaign is : ".$campaign['campaign_id']."<br />";
			foreach($campaign['users'] as $user){
				echo "user is : ".$user['user_id']. "<br />";
				echo "user_info: ";
				var_dump($user['user_info']);
				echo "<br />";
			}
		}*/
   }
   
   public function listImap(){
        $sql = "SELECT *
                FROM imap_info";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            if($stmt->rowCount()==0) 
			{
                echo "Empty imap_info table.";
            }
			else
			{
				for($i=0 ; $i<$stmt->rowCount() ; $i++){
    				$row = $stmt->fetch();
					$this->imap_info[$row['imap_id']] = $row;
				}
			}
		}
		else
		{
        	echo "Error! Sorry, Error in SQL.";
        }
   	}
   	
   	public function listSmtp(){
        $sql = "SELECT *
                FROM smtp_info";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            if($stmt->rowCount()==0) 
            {
                echo "Empty smtp_info table.";
            }
            else
            {
                for($i=0 ; $i<$stmt->rowCount() ; $i++){
                    $row = $stmt->fetch();
                    $this->smtp_info[$row['smtp_id']] = $row;
                }
            }
        }
        else
        {
            echo "Error! Sorry, Error in SQL.";
        }
    }

    public function limitation(){
    
        $userLimit = array();
        $userLimit['mailsuni'] = 0;
        $userLimit['pop'] = 0;
        $userLimit['expire'] = '2000-01-01 01:01:01';
        
        $sql = "SELECT mailsuni FROM mails where id='total'";
       if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            $row = $stmt->fetch();
            $userLimit['mailsuni'] = $row['mailsuni'];
       }

       $sql = "SELECT pop, expire FROM users where Username !='info.bytefact@gmail.com'";
       if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            $row = $stmt->fetch();
            $userLimit['pop'] = $row['pop'];
            $userLimit['expire'] = $row['expire'];
       }
       //echo "<pre>";
       //var_dump($userLimit);
       //echo "</pre>";
       return $userLimit;
   	}

   	public function countCampaignMessage(){
        $sql = "SELECT campaign_id, COUNT(message_id) AS theCount
                FROM message GROUP BY campaign_id;";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            if($stmt->rowCount()!=0) 
            {
                for($i=0 ; $i<$stmt->rowCount() ; $i++){
                    $row = $stmt->fetch();
                    $this->msg_cnt[$row['campaign_id']] = $row['theCount'];
                }
            }
            else
            {
                //echo "No messages defined in any campaign.";
            }
        }
        else
        {
            echo "Error! Sorry, Error in SQL.";
        }
    }
    
    public function countCampaignDelayMessage(){
        $sql = "SELECT campaign_id, COUNT(delay_message_id) AS theCount
                FROM delay_message GROUP BY campaign_id;";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->execute();
            if($stmt->rowCount()!=0) 
            {
                for($i=0 ; $i<$stmt->rowCount() ; $i++){
                    $row = $stmt->fetch();
                    $this->delay_msg_cnt[$row['campaign_id']] = $row['theCount'];
                }
            }
            else
            {
                //echo "No delay messages defined in any campaign.";
            }
        }
        else
        {
            echo "Error! Sorry, Error in SQL.";
        }
    }
   	
   public function doJob(){
		foreach($this->campaigns as $campaign){
            $limit = $this->limitation();

            if($limit['mailsuni'] > $limit['pop'] || (strtotime($limit['expire']) - strtotime("now")) < 0 ){
                echo "###### USER LICENSE EXPIRED ######";
                continue;
            }

            if($this->log_level > 3) echo "####Reading campaign:" .$campaign['campaign_id'] . "<br/>";
            $mails_read = $this->limitation();
            //if($mails_read > 1000) break;

            $userLimits = $this->shouldSkipMaster($campaign);
	    //echo "<pre>";
	    //var_dump($userLimits);
	    //echo "</pre>";

            $nMsgs = 0;
            if(isset($this->msg_cnt[$campaign['campaign_id']]))
                $nMsgs = $this->msg_cnt[$campaign['campaign_id']];
            if(isset($this->delay_msg_cnt[$campaign['campaign_id']]))
                $nMsgs = $nMsgs + $this->delay_msg_cnt[$campaign['campaign_id']];

            $notice = 'NO';
            if($userLimits['total'] == 0 && $nMsgs != 0){
                $notice = 'YES';
            }
            $id = 'campaign'.$campaign['campaign_id'];
            $sql = "UPDATE mails SET notice=:notice WHERE id=:id";
            if($stmt = $this->_db->prepare($sql)){
                $stmt->bindParam(":id", $id, PDO::PARAM_STR);
                $stmt->bindParam(":notice", $notice, PDO::PARAM_STR);
                $stmt->execute();
            }

			foreach($campaign['users'] as $user){
                if($this->log_level > 1) echo "Mailbox:" .$user['user_id'];
                //var_dump($userLimits);
                if($this->isCampaignMaster($user['user_id'], $campaign['campaign_id']) && $userLimits['total'] == 0){
                    echo "## Mail Sending quota full for all sender mails.";
                }
                else if(!isset($userLimits[$user['user_info']['mail_id']]) && !$this->isCampaignMaster($user['user_id'], $campaign['campaign_id'])){
                    continue;
                }
                else {
                    $userStatus = $this->readNewMail($user['user_info'], $this->imap_info[$user['user_info']['imap_id']], $userLimits, $campaign['campaign_id']);
                    $this->updateSchedule($campaign['campaign_id'], $userStatus, $user['user_id'], $userLimits);
				}
			}
		}
   }
   
   
   public function readNewMail($user, $imap, &$userLimits, $campaign_id){
   
		// IMAP must be enabled in Google Mail Settings		
		$user_id = $user['mail_id'];
		$user_password = $user['password'];
		$user_attachment_dir = dirname(__FILE__) . '/attachments';
		$imap_host = $imap['imap_host'];
		$imap_port = $imap['imap_port'];
		$imap_secure = $imap['imap_secure'];
		$imap_charset = $imap['imap_charset'];
		$imap_folder = 'INBOX';
		
		$takethemail = "@takethemail.com";
        if(strstr($user_id,$takethemail) != false){
            if($this->log_level > 3) echo "(Takethemail User)" . "<br/>";
            $imap_host = 'takethemail.com';
            $imap_port = 143;
            $imap_secure = 'novalidate-cert';
            
        }
		
		//echo "<br/>". $connection_string;
		//echo "<br/>" .$user_id . " " . $user_password . " " . $user_attachment_dir . " " . $imap_charset;
        
        $gmail = "@gmail.com";
        if(strstr($user_id,$gmail) != false){
            if($this->log_level > 3) echo "(Gmail User)" . "<br/>";
            $NewMails = $this->readNewGmail($user_id, $user_password);
        }
        else {
            if($imap['worked'] == 1){
                $connection_string = 
                        '{'.
                        $imap_host.
                        ':'.
                        $imap_port.
                        '/imap/'.
                        $imap_secure.
                        '}'.
                        $imap_folder
                        ;
                 $socket = fsockopen($imap_host, $imap_port, $errno, $errstr, 10); 
                 if($socket) 
                 {
                    try {
                        $mailbox = new ImapMailbox($connection_string, $user_id, $user_password, $user_attachment_dir);//, $user_attachment_dir, $imap_charset);
                        $NewMails = $mailbox->searchMailBox('UNSEEN');
                    }
                    catch(Exception $ex) {
                        echo $ex->getMessage();
                    }
                 }
                 else {
                    $sql = "UPDATE imap_info SET worked=0 
                                            WHERE imap_host=:imap_host AND imap_port=:imap_port AND imap_secure=:imap_secure";
                                if($stmt = $this->_db->prepare($sql)) {
                                    $stmt->bindParam(":imap_host", $imap_host, PDO::PARAM_STR);
                                    $stmt->bindParam(":imap_port", $imap_port, PDO::PARAM_INT);
                                    $stmt->bindParam(":imap_secure", $imap_secure, PDO::PARAM_STR);
                                    $stmt->execute();
                     }
                 }
            }
            else {
                //port : 143, 993
                //secure : ssl, tls, ssl/novalidate-cert
                $ports = array($imap_port, 993, 143);
                $secures = array($imap_secure, "ssl", "tls", "ssl/novalidate-cert", "novalidate-cert");
                for($i=0;$i<count($secures);$i++){
                    for($j=0;$j<count($ports);$j++){
                        $connection_string = 
                        '{'.
                        $imap_host.
                        ':'.
                        $ports[$j].
                        '/imap/'.
                        $secures[$i].
                        '}'.
                        $imap_folder
                        ;
                        $socket = fsockopen($imap_host, $ports[$j], $errno, $errstr, 10); 
                        if($socket) 
                        {
                            try {
                                $mailbox = new ImapMailbox($connection_string, $user_id, $user_password,$user_attachment_dir);//, $user_attachment_dir, $imap_charset);
                                $NewMails = $mailbox->searchMailBox('UNSEEN');
                            }
                            catch(Exception $ex){
                                echo $ex->getMessage();
                            }
                            if(is_array($NewMails)){
                                $sql = "UPDATE imap_info SET imap_port=:rimap_port, imap_secure=:rimap_secure, worked=1 
                                            WHERE imap_host=:imap_host AND imap_port=:imap_port AND imap_secure=:imap_secure";
                                if($stmt = $this->_db->prepare($sql)) {
                                    $stmt->bindParam(":rimap_port", $ports[$j], PDO::PARAM_INT);
                                    $stmt->bindParam(":rimap_secure", $secures[$i], PDO::PARAM_STR);
                                    $stmt->bindParam(":imap_host", $imap_host, PDO::PARAM_STR);
                                    $stmt->bindParam(":imap_port", $imap_port, PDO::PARAM_INT);
                                    $stmt->bindParam(":imap_secure", $imap_secure, PDO::PARAM_STR);
                                    $stmt->execute();
                                }
                                break;
                            }
                        }
                    }
                    if($j != count($ports)) break;
                }
            }
            if($this->log_level > 3) {
                echo "New mails:" . "<br/>";
                var_dump($NewMails);
                echo "<br/>";
                echo "<br/>";
            }
		}

		if(!is_array($NewMails)){
                echo "Mail read failed." . "<br/>";
				$sql = "UPDATE alias_mail SET worked=0 WHERE mail_id=:mail_id";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":mail_id", $user_id, PDO::PARAM_STR);
		            $stmt->execute();
				}
				$sql = "UPDATE sub_master_mail SET worked=0 WHERE mail_id=:mail_id";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":mail_id", $user_id, PDO::PARAM_STR);
		            $stmt->execute();
				}
				return array();
		}
		
		echo count($NewMails) . " New mails." . "<br/>";
		
		if(count($NewMails) > $userLimits['total'] && $this->isCampaignMaster($user_id, $campaign_id))
            $NewMails = array_slice($NewMails, 0, $userLimits['total']); 
		
		if(count($NewMails)==0) {
				$sql = "UPDATE alias_mail SET worked=1 WHERE mail_id=:mail_id";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":mail_id", $user_id, PDO::PARAM_STR);
		            $stmt->execute();
				}
				$sql = "UPDATE sub_master_mail SET worked=1 WHERE mail_id=:mail_id";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":mail_id", $user_id, PDO::PARAM_STR);
		            $stmt->execute();
				}
				return array();
		}

		$sql = "UPDATE alias_mail SET worked=1 WHERE mail_id=:mail_id";
		if($stmt = $this->_db->prepare($sql)) {
			$stmt->bindParam(":mail_id", $user_id, PDO::PARAM_STR);
		    $stmt->execute();
		}
		$sql = "UPDATE sub_master_mail SET worked=1 WHERE mail_id=:mail_id";
		if($stmt = $this->_db->prepare($sql)) {
			$stmt->bindParam(":mail_id", $user_id, PDO::PARAM_STR);
		    $stmt->execute();
		}
		
		$mail_headers = array();
		try {
            if(strstr($user_id,$gmail) != false){
                $mail_headers = $this->getGmailsInfo($NewMails, $user_id, $user_password ); //it will mark the mails as read as well
            }
            else {
                $mail_headers = $mailbox->getMailsInfo($NewMails);
                $mailbox->markMailsAsRead($NewMails);
            }
		}
		catch (Exception $ex){
            echo $ex->getMessage();
		}
		return $mail_headers;
		
   }
   
   public function gerFireTimeDiff($campaign_id, $message_id){
	   $sql = "SELECT delay
                FROM message WHERE campaign_id=:campaign_id AND message_id=:message_id";
        if($stmt = $this->_db->prepare($sql)) {
			$stmt->bindParam(":campaign_id", $campaign_id, PDO::PARAM_INT);
			$stmt->bindParam(":message_id", $message_id, PDO::PARAM_INT);
            $stmt->execute();
    		$row = $stmt->fetch();
			if(isset($row['delay'])) return $row['delay'];
			else return 0;
		}
		else
		{
        	echo "NO delay time found for a campaing and a message";
			return 0;
        }
   }

      public function shouldSkipMaster($campaign){
        $counter = 0;
        $userLimits = array();
        $userLimits['total'] = 0;
        foreach($campaign['users'] as $eachUser){
            
            $counter++;
            if($counter == 1) continue;
            
            $user = $eachUser['user_info'];
            if($user['worked'] == 0) continue;
            $hLimit = $this->smtp_info[$user['smtp_id']]['per_day'];
            $nMsgs = 0;
            if(isset($this->msg_cnt[$user['campaign_id']]))
                $nMsgs = $this->msg_cnt[$user['campaign_id']];
            if(isset($this->delay_msg_cnt[$user['campaign_id']]))
                $nMsgs = $nMsgs + $this->delay_msg_cnt[$user['campaign_id']];
            //echo $nMsgs;
            if($nMsgs > 0){
                $threshold = 70;
                $msg = (70 * $nMsgs) / 100;
                if($msg < 4.5) $msg = $nMsgs;
                $limit = floor($hLimit / $msg);

		$sql = "UPDATE mails SET poplimit=:limit WHERE id=:mail_id";
                if($stmt = $this->_db->prepare($sql)){
                    $stmt->bindParam(":mail_id", $user['mail_id'], PDO::PARAM_STR);
                    $stmt->bindParam(":limit", $limit, PDO::PARAM_INT);
                    $stmt->execute();
                }
            
                //update started_on if one day passed.
                $sql = "UPDATE mails SET mailsuni=0, started_on = NOW(), notice = 'NO'  WHERE id=:mail_id 
                        AND UNIX_TIMESTAMP(NOW()) > UNIX_TIMESTAMP(DATE_ADD(STR_TO_DATE(started_on,'%Y-%m-%d %H:%i:%s'), INTERVAL 1440 MINUTE))";
                if($stmt = $this->_db->prepare($sql)){
                    $stmt->bindParam(":mail_id", $user['mail_id'], PDO::PARAM_STR);
                    $stmt->execute();
                }
                
                //check if we should skip it due to mail sending limit exceeded.
                $sql = "SELECT id, mailsuni from mails WHERE id=:mail_id AND mailsuni < :limit";
                if($stmt = $this->_db->prepare($sql)){
                    $stmt->bindParam(":mail_id", $user['mail_id'], PDO::PARAM_STR);
                    $stmt->bindParam(":limit", $limit, PDO::PARAM_INT);
                    $stmt->execute();
                    $row = $stmt->fetch();
                    if(isset($row['id'])){
                        $userLimits['total'] = $userLimits['total'] + ($limit - $row['mailsuni']);
                        $userLimits[$row['id']] = $limit - $row['mailsuni'];
                    }
		    else {
			$userLimits[$user['mail_id']] = 0;
 		    }
                }
                $sql = "UPDATE mails SET notice='YES' WHERE id=:mail_id AND mailsuni >= :limit";
                if($stmt = $this->_db->prepare($sql)){
                    $stmt->bindParam(":mail_id", $user['mail_id'], PDO::PARAM_STR);
                    $stmt->bindParam(":limit", $limit, PDO::PARAM_INT);
                    $stmt->execute();
                }
            }
        }
        return $userLimits;
   }

   public function getBestSender(&$userLimits){
        $max = 0;
        $id = "";
        foreach($userLimits as $user => $limit){
            if($user == 'total') continue;
            if($limit > $max){
                $max = $limit;
                $id = $user;
            }
        }
        $userLimits['total'] = $userLimits['total'] -1;
        $userLimits[$id] = $userLimits[$id]-1;
        return $id;
   }
   
   public function shouldBeFiltered($mail_id){
        //var_dump($this->filter);
        foreach($this->filter as $flt){
            if(strlen($mail_id) >= strlen($flt))
              if(strpos($mail_id,$flt) !== false) return true;
            else 
              if(strpos($flt,$mail_id) !== false) return true;
        }
        return false;
   }
   
   public function isCampaignMaster($mail_id, $campaign_id){
        $sql = "SELECT sub_master_mail_id 
                FROM campaign WHERE campaign_id=:campaign_id";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->bindParam(":campaign_id", $campaign_id, PDO::PARAM_INT);
            $stmt->execute();
            $row = $stmt->fetch();
            if( isset($row['sub_master_mail_id']) && $mail_id == $row['sub_master_mail_id']){
                //echo $mail_id . " " . $row['sub_master_mail_id'];
                return true;
            }
        }
        return false;
   }
   
   public function updateSchedule($campaign_id, $userStatus, $user_id, &$userLimits){
        $readMailCnt = count($userStatus);
        $total = 'total';
        $campaign = 'campaign'.$campaign_id;
        $user = $user_id;
        $sql = "UPDATE mails set mailsread=mailsread+:readMailCnt WHERE id=:total || id=:camapign || id=:user";
        if($stmt = $this->_db->prepare($sql)) {
            $stmt->bindParam(":readMailCnt", $readMailCnt, PDO::PARAM_INT);
            $stmt->bindParam(":total", $total, PDO::PARAM_STR);
            $stmt->bindParam(":camapign", $campaign, PDO::PARAM_STR);
            $stmt->bindParam(":user", $user, PDO::PARAM_STR);
            $stmt->execute();
        }
	   foreach($userStatus as $mail){
		    //var_dump($mail); 
		   
			$repleace_str = array('<','>');
			
			$from_arr = explode(' ',chop(str_replace($repleace_str,' ', $mail->from)));
			$from = $from_arr[count($from_arr)-1];
			
			$from_name = "";
			for($i=0;$i<count($from_arr)-1;$i++){
			    $from_name = $from_name . " " . $from_arr[$i];
			}
			$from_name = chop($from_name);
			
			//check if it should be filtered
			if($this->shouldBeFiltered($from)){
			    if($this->log_level > 0)echo "#Skipped:" . $from . " Reason: Mail ID Filter<br/>";
                $sql = "UPDATE mails set mailsskipped=mailsskipped+1 WHERE id=:total || id=:camapign || id=:user";
                if($stmt = $this->_db->prepare($sql)) {
                    $stmt->bindParam(":total", $total, PDO::PARAM_STR);
                    $stmt->bindParam(":camapign", $campaign, PDO::PARAM_STR);
                    $stmt->bindParam(":user", $user, PDO::PARAM_STR);
                    $stmt->execute();
                }
			    continue;
			}
			
			//check if the mail server property_exists
			list($userName, $mailDomain) = explode("@", $from); 
			if (!checkdnsrr($mailDomain, "MX")) {
			    if($this->log_level > 0)echo "#Skipped:" . $from . " Reason: NO Mail Server Present<br/>";
			    $sql = "UPDATE mails set mailsskipped=mailsskipped+1 WHERE id=:total || id=:camapign || id=:user";
                if($stmt = $this->_db->prepare($sql)) {
                    $stmt->bindParam(":total", $total, PDO::PARAM_STR);
                    $stmt->bindParam(":camapign", $campaign, PDO::PARAM_STR);
                    $stmt->bindParam(":user", $user, PDO::PARAM_STR);
                    $stmt->execute();
                }
			    continue;
			} 
			
			
			$to_arr = explode(' ',chop(str_replace($repleace_str,' ', $mail->to)));
			$to = $to_arr[count($to_arr)-1];
			
			$go_id_arr = explode(' ',chop(str_replace($repleace_str,' ', $mail->message_id)));
			$go_id = $go_id_arr[count($go_id_arr)-1];
			
			$in_reply_to_arr = explode(' ',chop(str_replace($repleace_str,' ', property_exists($mail, 'in_reply_to')?$mail->in_reply_to:" ")));
			$in_reply_to = $in_reply_to_arr[count($in_reply_to_arr)-1];
			$subject = "Re: ".$mail->subject;

			//echo "from:#".$from ."#<br/>";
			//echo "to:#".$to."#<br/>";
			//echo "msgid:#".$go_id."#<br/>";
			//echo "in reply to:#".$in_reply_to.'#<br/>';
			
			//Alter send_delay_mail table for the specified from and to
			$never = '2020-01-01 00:00:01';
			$sql = "UPDATE send_delay_mail 
					SET fire=:never
					WHERE
						from_mail=:from
					";
        	if($stmt = $this->_db->prepare($sql)) {
				$stmt->bindParam(":from", $from, PDO::PARAM_STR);
				$stmt->bindParam(":never", $never, PDO::PARAM_STR);
            	$stmt->execute();
			}
			else
			{
        		echo "Error! Sorry, Error in SQL.";
        	}
			
			//Check if this is the first mail
			$mail_count = 0;
			$sql = "SELECT count
             		   FROM send_mail
					   WHERE from_mail=:from";
			if($stmt = $this->_db->prepare($sql)) {
				$stmt->bindParam(":from", $from, PDO::PARAM_STR);
				$stmt->execute();
				$row = $stmt->fetch();
				if(isset($row['count'])) {
					$mail_count = $row['count'];
				}
				else $mail_count = 0;
			}
			
			if(!$this->isCampaignMaster($user_id, $campaign_id) && $mail_count == 0){
                if($this->log_level > 0)echo "#Skipped:" . $from . " Reason: Mail not initiated from Popping mail.<br/>";
                //$sql = "UPDATE mails set mailsskipped=mailsskipped+1 WHERE id=:total || id=:camapign || id=:user";
                //if($stmt = $this->_db->prepare($sql)) {
                //    $stmt->bindParam(":total", $total, PDO::PARAM_STR);
                //    $stmt->bindParam(":camapign", $campaign, PDO::PARAM_STR);
                //    $stmt->bindParam(":user", $user, PDO::PARAM_STR);
                //    $stmt->execute();
               //}
                continue; 
			}
			
			if( $mail_count == 0
			
				//(!isset($in_reply_to) || $in_reply_to == "") && $mail_count == 0)
				//|| (isset($in_reply_to) && $in_reply_to != "" && $mail_count == 0)
				){
				//So, no mail communication is going on or the whole communication is already over. So, insert a column in
				//send_mail to fire as we will consider it as the first mail.
				//from: defined already
				//go_id: defined already
				$count = 1;
				//campaign_id: defined already
				$message_id = $count;
				$sender = $this->getBestSender($userLimits);
				if($sender == "") continue;
				$next_fire = $this->gerFireTimeDiff($campaign_id, $message_id);
				$fire = date("Y-m-d H:i:s", strtotime("+{$next_fire} minutes", time()));
				$sql = "INSERT INTO send_mail(	from_mail, go_id, count, campaign_id, message_id, fire, isFired, subject, sender, from_name)
                VALUES(:from, :go_id, :count, :campaign_id, :message_id, :fire, 0, :subject, :sender, :from_name)";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":from", $from, PDO::PARAM_STR);
					$stmt->bindParam(":from_name", $from_name, PDO::PARAM_STR);
					$stmt->bindParam(":go_id", $go_id, PDO::PARAM_STR);
					$stmt->bindParam(":count", $count, PDO::PARAM_INT);
					$stmt->bindParam(":campaign_id", $campaign_id, PDO::PARAM_INT);
					$stmt->bindParam(":message_id", $message_id, PDO::PARAM_INT);
					$stmt->bindParam(":fire", $fire, PDO::PARAM_STR);
					$stmt->bindParam(":subject", $subject, PDO::PARAM_STR);
					$stmt->bindParam(":sender", $sender, PDO::PARAM_STR);
					$stmt->execute();
					$stmt->closeCursor();
		
					$userID = $this->_db->lastInsertId();
					$succeed = dechex($userID);
				} else {
					echo "error in INSERT send_mail table for first mail fire insert";
				}
				$sql = "UPDATE mails set mailsuni=mailsuni+1, mailstotaluni=mailstotaluni+1 WHERE id=:total || id=:camapign || id=:user || id=:sender";
                if($stmt = $this->_db->prepare($sql)) {
                    $stmt->bindParam(":total", $total, PDO::PARAM_STR);
                    $stmt->bindParam(":camapign", $campaign, PDO::PARAM_STR);
                    $stmt->bindParam(":user", $user, PDO::PARAM_STR);
                    $stmt->bindParam(":sender", $sender, PDO::PARAM_STR);
                    $stmt->execute();
                }
				
			}
			//Ok,this is not first mail. Lets update the send_mail count table.
			else{
				$mail_count = $mail_count + 1;
				$message_id = $mail_count;
				$next_fire = $this->gerFireTimeDiff($campaign_id, $message_id);
				$fire = "2020-01-01 00:00:01";
				if($this->gerFireTimeDiff($campaign_id, $message_id)){
					$fire = date("Y-m-d H:i:s", strtotime("+{$next_fire} minutes", time()));
				}
				$sql = "UPDATE send_mail 
					SET go_id=:go_id,
					count=count+1,
					message_id=message_id+1,
					fire=:fire,
					isFired=0
					WHERE
						from_mail=:from AND isFired = 1
					";
				if($stmt = $this->_db->prepare($sql)) {
					$stmt->bindParam(":from", $from, PDO::PARAM_STR);
					$stmt->bindParam(":go_id", $go_id, PDO::PARAM_STR);
					$stmt->bindParam(":fire", $fire, PDO::PARAM_STR);
					$stmt->execute();
				}
				else
				{
					echo "Error! Sorry, Error in SQL.";
				}
			}
	   }
   }
}
?>
